package com.tbynet.jwp.repository.impl;

import com.jfinal.kit.PathKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.tbynet.jwp.framework.aop.Aop;
import com.tbynet.jwp.framework.core._JwpServiceProvider;
import com.tbynet.jwp.framework.kit.DateKit;
import com.tbynet.jwp.model.Posts;
import com.tbynet.jwp.repository.spi.PostBackupService;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Aop(PostBackupService.class)
public class PostBackupServiceImpl extends _JwpServiceProvider<Posts> implements PostBackupService {

    private static final String BACKUP_DIR = PathKit.getWebRootPath() + "/backups/posts/";
    private static final String BACKUP_PREFIX = "post_backup_";

    static {
        // 确保备份目录存在
        File backupDir = new File(BACKUP_DIR);
        if (!backupDir.exists()) {
            backupDir.mkdirs();
        }
    }

    @Override
    protected String buildSearchWhereSql(String keyword, List<Object> params) {
        return "";
    }

    @Override
    public String createBackup(String backupType) {
        try {
            String timestamp = DateKit.format(new Date(), "yyyyMMdd_HHmmss");
            String fileName = BACKUP_PREFIX + timestamp + "_" + backupType + ".zip";
            String filePath = BACKUP_DIR + fileName;

            // 创建备份文件
            try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(filePath))) {

                // 备份文章数据
                backupPostsData(zos);

                // 备份分类数据
                backupTermsData(zos);

                // 备份元数据
                backupMetadata(zos);

                // 添加备份信息文件
                addBackupInfo(zos, backupType, timestamp);
            }

            return fileName;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean restoreBackup(String backupFile) {
        try {
            String filePath = BACKUP_DIR + backupFile;
            File file = new File(filePath);

            if (!file.exists()) {
                return false;
            }

            // 这里实现恢复逻辑
            // 1. 解压备份文件
            // 2. 读取备份数据
            // 3. 恢复数据到数据库

            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public List<BackupInfo> getBackupList() {
        List<BackupInfo> backupList = new ArrayList<>();
        File backupDir = new File(BACKUP_DIR);

        if (backupDir.exists() && backupDir.isDirectory()) {
            File[] files = backupDir.listFiles((dir, name) -> name.startsWith(BACKUP_PREFIX));

            if (files != null) {
                for (File file : files) {
                    BackupInfo info = new BackupInfo();
                    info.setFileName(file.getName());
                    info.setCreateTime(new Date(file.lastModified()));
                    info.setFileSize(file.length());
                    info.setBackupType(extractBackupType(file.getName()));
                    backupList.add(info);
                }
            }
        }

        // 按创建时间倒序排列
        backupList.sort((a, b) -> b.getCreateTime().compareTo(a.getCreateTime()));

        return backupList;
    }

    @Override
    public boolean deleteBackup(String backupFile) {
        try {
            String filePath = BACKUP_DIR + backupFile;
            File file = new File(filePath);

            if (file.exists()) {
                return file.delete();
            }

            return false;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void autoBackup() {
        // 检查是否需要自动备份
        if (shouldAutoBackup()) {
            createBackup("auto");
        }
    }

    @Override
    public boolean exportBackup(String backupFile, String remoteType) {
        // 实现备份文件导出到远程存储（如FTP、云存储等）
        // 暂时返回true表示成功
        return true;
    }

    @Override
    public boolean importBackup(String remoteFile, String remoteType) {
        // 实现从远程存储导入备份文件
        // 暂时返回true表示成功
        return true;
    }

    /**
     * 备份文章数据
     */
    private void backupPostsData(ZipOutputStream zos) throws IOException {
        List<Posts> posts = new Posts().dao().find("SELECT * FROM wp_posts WHERE post_type = 'post'");

        StringBuilder csvContent = new StringBuilder();
        csvContent.append("ID,Title,Content,Excerpt,Status,Author,Date,Modified,CommentStatus,PingStatus\n");

        for (Posts post : posts) {
            csvContent.append(post.getID()).append(",")
                    .append(escapeCsv(post.getPostTitle())).append(",")
                    .append(escapeCsv(post.getPostContent())).append(",")
                    .append(escapeCsv(post.getPostExcerpt())).append(",")
                    .append(post.getPostStatus()).append(",")
                    .append(post.getPostAuthor()).append(",")
                    .append(DateKit.format(post.getPostDate(), "yyyy-MM-dd HH:mm:ss")).append(",")
                    .append(DateKit.format(post.getPostModified(), "yyyy-MM-dd HH:mm:ss")).append(",")
                    .append(post.getCommentStatus()).append(",")
                    .append(post.getPingStatus()).append("\n");
        }

        ZipEntry entry = new ZipEntry("posts.csv");
        zos.putNextEntry(entry);
        zos.write(csvContent.toString().getBytes("UTF-8"));
        zos.closeEntry();
    }

    /**
     * 备份分类数据
     */
    private void backupTermsData(ZipOutputStream zos) throws IOException {
        String sql = "SELECT t.term_id, t.name, t.slug, tt.taxonomy, tt.description, tt.parent " +
                "FROM wp_terms t " +
                "INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id " +
                "WHERE tt.taxonomy IN ('category', 'post_tag')";

        List<Record> terms = Db.find(sql);

        StringBuilder csvContent = new StringBuilder();
        csvContent.append("TermID,Name,Slug,Taxonomy,Description,Parent\n");

        for (Record term : terms) {
            csvContent.append(term.getBigInteger("term_id")).append(",")
                    .append(escapeCsv(term.getStr("name"))).append(",")
                    .append(term.getStr("slug")).append(",")
                    .append(term.getStr("taxonomy")).append(",")
                    .append(escapeCsv(term.getStr("description"))).append(",")
                    .append(term.getBigInteger("parent")).append("\n");
        }

        ZipEntry entry = new ZipEntry("terms.csv");
        zos.putNextEntry(entry);
        zos.write(csvContent.toString().getBytes("UTF-8"));
        zos.closeEntry();
    }

    /**
     * 备份元数据
     */
    private void backupMetadata(ZipOutputStream zos) throws IOException {
        // 备份文章关系数据
        backupTermRelationships(zos);
        backupPostMeta(zos);
    }

    /**
     * 备份分类关系
     */
    private void backupTermRelationships(ZipOutputStream zos) throws IOException {
        List<Record> relationships = Db.find("SELECT * FROM wp_term_relationships");

        StringBuilder csvContent = new StringBuilder();
        csvContent.append("ObjectID,TermTaxonomyID,TermOrder\n");

        for (Record rel : relationships) {
            csvContent.append(rel.getBigInteger("object_id")).append(",")
                    .append(rel.getBigInteger("term_taxonomy_id")).append(",")
                    .append(rel.getInt("term_order")).append("\n");
        }

        ZipEntry entry = new ZipEntry("term_relationships.csv");
        zos.putNextEntry(entry);
        zos.write(csvContent.toString().getBytes("UTF-8"));
        zos.closeEntry();
    }

    /**
     * 备份文章元数据
     */
    private void backupPostMeta(ZipOutputStream zos) throws IOException {
        List<Record> postMeta = Db.find("SELECT * FROM wp_postmeta WHERE post_id IN (SELECT ID FROM wp_posts WHERE post_type = 'post')");

        StringBuilder csvContent = new StringBuilder();
        csvContent.append("MetaID,PostID,MetaKey,MetaValue\n");

        for (Record meta : postMeta) {
            csvContent.append(meta.getBigInteger("meta_id")).append(",")
                    .append(meta.getBigInteger("post_id")).append(",")
                    .append(escapeCsv(meta.getStr("meta_key"))).append(",")
                    .append(escapeCsv(meta.getStr("meta_value"))).append("\n");
        }

        ZipEntry entry = new ZipEntry("post_meta.csv");
        zos.putNextEntry(entry);
        zos.write(csvContent.toString().getBytes("UTF-8"));
        zos.closeEntry();
    }

    /**
     * 添加备份信息文件
     */
    private void addBackupInfo(ZipOutputStream zos, String backupType, String timestamp) throws IOException {
        StringBuilder infoContent = new StringBuilder();
        infoContent.append("Backup Type: ").append(backupType).append("\n");
        infoContent.append("Backup Time: ").append(timestamp).append("\n");
        infoContent.append("Database Version: ").append(getDatabaseVersion()).append("\n");
        infoContent.append("Total Posts: ").append(getTotalPostCount()).append("\n");

        ZipEntry entry = new ZipEntry("backup_info.txt");
        zos.putNextEntry(entry);
        zos.write(infoContent.toString().getBytes("UTF-8"));
        zos.closeEntry();
    }

    /**
     * CSV转义
     */
    private String escapeCsv(String value) {
        if (value == null) return "";
        if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
            return "\"" + value.replace("\"", "\"\"") + "\"";
        }
        return value;
    }

    /**
     * 提取备份类型
     */
    private String extractBackupType(String fileName) {
        // 从文件名中提取备份类型
        if (fileName.contains("_auto_")) return "auto";
        if (fileName.contains("_manual_")) return "manual";
        if (fileName.contains("_full_")) return "full";
        return "unknown";
    }

    /**
     * 检查是否需要自动备份
     */
    private boolean shouldAutoBackup() {
        // 这里可以实现自动备份策略
        // 例如：每天备份一次，或者文章数量达到一定阈值时备份
        return true;
    }

    /**
     * 获取数据库版本
     */
    private String getDatabaseVersion() {
        Record version = Db.findFirst("SELECT option_value FROM wp_options WHERE option_name = 'db_version'");
        return version != null ? version.getStr("option_value") : "unknown";
    }

    /**
     * 获取文章总数
     */
    private int getTotalPostCount() {
        return Db.queryInt("SELECT COUNT(*) FROM wp_posts WHERE post_type = 'post'");
    }
}
